package com.schoolegard.services.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;

import com.schoolegard.services.DeviceService;
import com.schoolgard.dao.DeviceDao;
import com.schoolgard.dao.HdStateDao;
import com.schoolgard.dao.ParamServerDao;
import com.schoolgard.entitybean.Device;
import com.schoolgard.entitybean.HdState;
import com.schoolgard.entitybean.ParamServer;

public class DeviceServiceImpl implements DeviceService {
	
	private static Logger logger = Logger.getLogger(DeviceServiceImpl.class);
	
	private DeviceDao deviceDao;
	private ParamServerDao paramServerDao; 
	private HdStateDao hdStateDao;

	public HdStateDao getHdStateDao() {
		return hdStateDao;
	}
	public void setHdStateDao(HdStateDao hdStateDao) {
		this.hdStateDao = hdStateDao;
	}
	public void setDeviceDao(DeviceDao deviceDao) {
		this.deviceDao = deviceDao;
	}
	public void setParamServerDao(ParamServerDao paramServerDao) {
		this.paramServerDao = paramServerDao;
	}


	@Override
	public List<Device> findByOrganization(Long orgId) {
		return deviceDao.find("from Device where organization.id = "+orgId);
	}

	@Override
	public List<Device> findAll() {
		return deviceDao.findAll();
	}

	@Override
	public Device findById(String guid) {
		DetachedCriteria criteria = DetachedCriteria.forClass(Device.class);
		criteria.add(Restrictions.eq("guid", guid));
		List<Device> devices = deviceDao.findByCriteria(criteria);
		return (devices!= null && devices.size() > 0)?devices.get(0):null;
	}

	@Override
	public void saveOrUpdate(Device device) {
		
		deviceDao.createOrModify(device);
	}

	@Override
	public List<Device> findByParentId(String parentId) {
		DetachedCriteria criteria = DetachedCriteria.forClass(Device.class);
		criteria.add(Restrictions.eq("parentDeviceGuid", parentId));
		return deviceDao.findByCriteria(criteria);
	}

	@Override
	public void delete(String guid) {
		ParamServer ps = paramServerDao.findById(guid);
		if(ps != null) {
			paramServerDao.remove(ps);
		}
		HdState state = hdStateDao.findById(guid);
		if(state != null) {
			hdStateDao.remove(state);
		}
		deviceDao.remove(findById(guid));
	}
	public List<Device> findNoInNet(String serial,int first,int max) {
		DetachedCriteria criteria = DetachedCriteria.forClass(Device.class);
		criteria.add(Restrictions.eq("organization.id", -1L));
		if(StringUtils.isNotEmpty(serial)){
			criteria.add(Restrictions.eq("serial", serial));
		}
		return deviceDao.findByCriteria(criteria, first, max);
	}
	
	public List<Device> findByAnyId(String id) {
		if(StringUtils.isEmpty(id)){
			return new ArrayList<Device>();
		}
		DetachedCriteria criteria = DetachedCriteria.forClass(Device.class);
		if(id.indexOf("re_") != -1) {
			id = id.replace("re_", "");
			criteria.createAlias("organization", "organization");
			criteria.add(Restrictions.in("organization.regions.id",getRegions(Long.valueOf(id))));
		}else if(id.indexOf("or_") != -1) {
			id = id.replace("or_", "");
			criteria.add(Restrictions.in("organization.id",getOrganizations(Long.valueOf(id))));
		}else if(id.indexOf("de_") != -1) {
			id = id.replace("de_", "");
			criteria.add(Restrictions.eq("guid",id));
		}
		return deviceDao.findByCriteria(criteria);
	}
	
	private List<Long> getRegions(Long id){
		try{
			String sql = "select id  FROM regions START WITH parent_ID = "+id+" CONNECT BY PRIOR ID = parent_ID";
			List<BigDecimal> list = (ArrayList<BigDecimal>)deviceDao.getResultBySql(sql);
			List<Long> ids = new ArrayList<Long>();
			if(list != null && list.size() > 0) {
				for(int i = 0;i < list.size();i++) {
					ids.add(list.get(i).longValue());
				}
			}
			ids.add(id);
			return ids;
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}
	}
	
	private List<Long> getOrganizations(Long id){
		try{
			String sql = "SELECT id FROM organization START WITH parent_ID = "+id+" CONNECT BY PRIOR ID = parent_ID";
			List<BigDecimal> list = (ArrayList<BigDecimal>)deviceDao.getResultBySql(sql);
			List<Long> ids = new ArrayList<Long>();
			if(list != null && list.size() > 0) {
				for(int i = 0;i < list.size();i++) {
					ids.add(list.get(i).longValue());
				}
			}
			ids.add(id);
			return ids;
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}
	}
	
	public String findRouter(Device device){
		if(device == null) {
			return "";
		}
		String router = device.getGuid();
		String parentGuid = device.getParentDeviceGuid();
		if(StringUtils.isNotEmpty(parentGuid)) {
			Device parent = this.findById(parentGuid);
			router = router+"."+findRouter(parent);
		}
		return router;
	}
}
